package org.eda2;

import java.util.ArrayList;
import java.util.Collections;

/**
 * Clase LocalidadGreedy. Clase que mediante la tecnica Greedy, por localidad
 * entre usuarios, devuelve los usuarios que maximizan el beneficio de su
 * estudio en base a dicha localidad.
 */
public class LocalidadGreedy {

	/**
	 * THe listaSolucion. Atributo de clase. Hace eferencia a la lista de
	 * usuarios como solucion a la practica.
	 */
	private ArrayList<User> listaSolucion;

	/**
	 * Metodo LocalidadGreedy. Metodo constructor de la clase. Metodo que genera
	 * la lista de los usuarios que maximizan el beneficio en base al estudio de
	 * la lista generada por cualquiera de los 2 metodos anteriores DyV o Greedy
	 * de los usuarios iniciales al estudio (P1-P2a).
	 * 
	 * @param listaUsuarios
	 *            . Variable de tipo ArrayList. Hace referencia a todos los
	 *            usuarios sin filtrar.
	 * @param listaPareto
	 *            . Variable de tipo ArrayList. Hace referencia a los usuarios
	 *            candidatos tras el primer filtrado.
	 * @param localidad
	 *            . Variable de tipo int. Hace referencia a la localidad de
	 *            estudio de los usuarios tras un primer filtrado, o sea, que
	 *            para calcular el beneficio de cada uno de los usuarios del
	 *            primer filtrado, necesito realizar una media con los usuarios
	 *            (localidad) que esten mas cerca de el, en la lista inicial de
	 *            usuarios.
	 */
	public LocalidadGreedy(ArrayList<User> listaUsuarios,
			ArrayList<User> listaPareto, int localidad) {

		this.listaSolucion = new ArrayList<User>();

		// Para todos los usuarios de la lista de candidatos...
		for (User user : listaPareto) {
			ArrayList<User> aux = new ArrayList<User>();

			// Obtenemos la posicion en la lista total de usuarios...
			int index = listaUsuarios.indexOf(user);

			// Determinamos los parametros para poder movernos por la lista de
			// usuarios totales...
			int i = index - localidad;
			int j = index + localidad;

			// Si la i es negativa, nos quedamos con la parte positiva solo...
			if (i < 0)
				i = localidad + i;
			else
				i = localidad;

			// Si la j supera al numero de elementos, nos quedamos solo con la
			// diferencia...
			if (j >= listaUsuarios.size())
				j = (listaUsuarios.size() - 1) - index;
			else
				j = localidad;

			// Insertamos los superiores con el indice i...
			for (; i > 0; i--)
				aux.add(listaUsuarios.get(index - i));

			// Insertamos los inferiores con el indice j...
			for (; j > 0; j--)
				aux.add(listaUsuarios.get(index + j));

			// Insertamos el modulo calculado en cada uno de los usuarios del
			// doble filtrado...
			for (User user2 : aux)
				user2.setModulo(Math.abs(user.getIce() - user2.getIce()));

			// Ordenamos los usuarios del doble liftrado por el su modulo...
			Collections.sort(aux, new UserComparatorModulo());
			int suma = 0;
			int k = 0;

			// Calculamos la suma total de CE, de un numero total de usuarios
			// igual a la localidad.
			for (; (k < localidad && k < aux.size()); k++)
				suma += aux.get(k).getCe();

			// Obtenemos el mcl, como la media entre la suma y el numero de
			// usuarios que intervinieron en el calculo...
			int mclValor = suma / k;

			// Modificamos el valor de mcl del usuario del primer filtrado...
			user.setMcl(mclValor);

			// Modificamos el valor de la diferencia del usuario del primer
			// filtrado...
			user.setDiferencia(user.getMcl() - user.getCe());
		}

		// Ordenamos la lista de usuarios del primer filtrado, segun la
		// diferencia, de mayor a menor...
		Collections.sort(listaPareto, new UserComparatorDiferencia());

		// Obtenemos una lista con un segundo filtrado, con exactamente el 5% de
		// los usuarios de la lista inicial...
		this.listaSolucion.addAll(listaPareto.subList(0,
				(listaUsuarios.size() / 200)));
	}

	/**
	 * Metodo getListaSolucion. Metodo que devuelve el atributo de clase
	 * listaSolucion.
	 * 
	 * @return variable de tipo ArrayList<User>. Hace referencia a la lista de
	 *         usuarios seleccionados.
	 */
	public ArrayList<User> getListaSolucion() {
		return this.listaSolucion;
	}
}
